
/*-----------------------------------------------------------------------------\
|                          ChipCFlow Block2Code V1.0                           |
|                                                                              |
| Desenvolvedor: Felipe Simões Lage Gomes Duarte                               |
| Orientador: Prof. Dr. Jorge Luiz e Silva                                     |
| Supervisor: Bruno de Abreu Silva                                             |
|	      Joelmir José Lopes                                               |
|                                                                              |
| Main Project: ChipCflow                                                      |
| Período: Agosto de 2009 a Julho de 2010                                      |
| Codigo: Traducao.java                                                        |
| Versão da IDE: NetBeans IDE 6.8 (Build 200912041610)                         |
| Java: 1.6.0_18; Java HotSpot(TM) Client VM 16.0-b13                          |
| Sistema Operacional: Windows 7 versão 6.1 executando em x86; pt_BR           |
|                                                                              |
|             O presente trabalho foi realizado com apoio do CNPq              |
|   Conselho Nacional de Desenvolvimento Científico  e Tecnológico - Brasil    |
\-----------------------------------------------------------------------------*/
package Tradutor;//Nome do pacote de dados.

import java.io.*;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

class compileException extends Exception {

  public compileException(String message) {
    super(message);
  }
}

public class Traducao {

  private static File CompileFile = null;
  private String ProjectName;
  private String ProjectPath;
  private FileOutputStream fOut;

  public boolean start() throws Exception {
    //if (isAllConected()) {
      creatFiles();
      copyFiles();
      fOut = new FileOutputStream(CompileFile);
      printHeader(fOut);
      addBibliotecas(fOut);
      //addEntity(fOut);
      //addArchitecture(fOut);
      //addDados(fOut);
      fOut.close();
    //}
    JOptionPane.showMessageDialog(null, "Arquivo Compilado com Sucesso \nCodigo "
            + "gerado com sucesso", "Sucesso", JOptionPane.INFORMATION_MESSAGE);
    return true;
  }

  private void printHeader(OutputStream out) throws IOException {
    String aux = ""
            + "-------------------------------------------------------------------------------\n"
            + "--                          ChipCFlow Block2Code V1.0                           \n"
            + "--                                                                              \n"
            + "-- Desenvolvedor: Felipe Simoes Lage Gomes Duarte                               \n"
            + "-- Orientador: Prof. Dr. Jorge Luiz e Silva                                     \n"
            + "--                                                                              \n"
            + "-- Codigo gerado automaticamente pela ferramento ChipCFlow Block2Code           \n"
            + "--                                                                              \n"
            + "-----------------------------------------------------------------------------\n\n\r";
    out.write(aux.getBytes(), 0, aux.length());
  }

  private void addBibliotecas(FileOutputStream fOut) throws compileException {
    String texto = " LIBRARY IEEE;                  "
            + " \n USE IEEE.STD_LOGIC_1164.ALL;     "
            + " \n USE IEEE.STD_LOGIC_ARITH.ALL;    "
            + " \n USE IEEE.STD_LOGIC_UNSIGNED.ALL; \n\n";
    try {
      fOut.write(texto.getBytes(), 0, texto.length());
    } catch (IOException ex) {
      throw new compileException(ex.toString());
    }
  }
  
  
  /*
   * Copy Files
   */
  
  private void copy(File src, File dst) throws compileException {
    // Copies src file to dst file.
    // If the dst file does not exist, it is created
    InputStream in;
    OutputStream out;
    byte[] buf = new byte[1024];
    int len;
    try {
      in = new FileInputStream(src);
      out = new FileOutputStream(dst); // Transfer bytes from in to out

      printHeader(out);

      // Copia dos arquivos
      while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
      }

      //fecha o arquivo lido e o copiado
      in.close();
      out.close();

    } catch (Exception ex) {
      throw new compileException(ex.toString());
    }
  }

  private void creatFiles() throws compileException {
    JFileChooser JanelaArquivo = new JFileChooser();//Aloca Janela SaveFile
    JanelaArquivo.setFileFilter(new FileNameExtensionFilter("Arquivo Codigo VHDL (*.vhd)", "vhd"));//Coloca filtro na Janela SaveFile
    int returnVal = JanelaArquivo.showSaveDialog(null);//retorna o botao precionado
    if (returnVal == JFileChooser.APPROVE_OPTION) {
      File auxFile = JanelaArquivo.getSelectedFile();
      this.ProjectName = auxFile.getName();
      this.ProjectPath = auxFile.getPath().substring(0, auxFile.getAbsolutePath().lastIndexOf('\\') + 1);
      auxFile.mkdir();
      this.ProjectPath = this.ProjectPath + "\\" + this.ProjectName;
      CompileFile = new File(this.ProjectPath + "\\" + this.ProjectName + ".vhd");
    } else {
      throw new compileException("Tradução cancelada pelo usuário");
    }
  }

  private void copyFiles() throws compileException {
   /* Operadores OpAux;
    boolean branchFlag = false,
            copyFlag = false,
            dmergeFlag = false,
            deciderFlag = false,
            operatorFlag = false,
            vdmergeFlag = false,
            inFlag = false,
            outFlag = false;

    for (int i = 0; i < d.size(); i++) {
      if (d.get(i) != null) {
        int size = d.get(i).getOp().size();
        for (int j = 0; j < size; j++) {
          OpAux = d.get(i).getOp().get(j);
          if (OpAux instanceof Branch && !branchFlag) {
            File src = new File("src/Codigos/BRANCH.vhd");
            File dst = new File(this.ProjectPath + "\\BRANCH.vhd");
            copy(src, dst);
            Block2Code.logAdd("'BRANCH.vhd' copiado com sucesso");
            branchFlag = true;
          } else if (OpAux instanceof Copy && !copyFlag) {
            File src = new File("src/Codigos/COPY.vhd");
            File dst = new File(this.ProjectPath + "\\COPY.vhd");
            copy(src, dst);
            Block2Code.logAdd("'COPY.vhd' copiado com sucesso");
            copyFlag = true;
          } else if (OpAux instanceof DMerge && !dmergeFlag) {
            File src = new File("src/Codigos/VDMERGE.vhd");
            File dst = new File(this.ProjectPath + "\\VDMERGE.vhd");
            copy(src, dst);
            Block2Code.logAdd("'VDMERGE.vhd' copiado com sucesso");
            dmergeFlag = true;
          } else if (OpAux instanceof Decider && !deciderFlag) {
            File src = new File("src/Codigos/DECIDERG.vhd");
            File dst = new File(this.ProjectPath + "\\DECIDERG.vhd");
            copy(src, dst);
            Block2Code.logAdd("'DECIDERG.vhd' copiado com sucesso");
            deciderFlag = true;
          } else if (OpAux instanceof NDMerge && !vdmergeFlag) {
            File src = new File("src/Codigos/NDMERGE.vhd");
            File dst = new File(this.ProjectPath + "\\NDMERGE.vhd");
            copy(src, dst);
            Block2Code.logAdd("'NDMERGE.vhd' copiado com sucesso");
            vdmergeFlag = true;
          } else if (OpAux instanceof Operator && !operatorFlag) {
            File src = new File("src/Codigos/OPERATOR.vhd");
            File dst = new File(this.ProjectPath + "\\OPERATOR.vhd");
            copy(src, dst);
            Block2Code.logAdd("'OPERATOR.vhd' copiado com sucesso");
            operatorFlag = true;
          } else if (OpAux instanceof In && !inFlag) {
            File src = new File("src/Codigos/INDATA.vhd");
            File dst = new File(this.ProjectPath + "\\INDATA.vhd");
            copy(src, dst);
            Block2Code.logAdd("'INDATA.vhd' copiado com sucesso");
            inFlag = true;
          } else if (OpAux instanceof Out && !outFlag) {
            File src = new File("src/Codigos/AOUT.vhd");
            File dst = new File(this.ProjectPath + "\\AOUT.vhd");
            copy(src, dst);
            Block2Code.logAdd("'AOUT.vhd' copiado com sucesso");
            inFlag = true;
          }
        }
      }
    }*/
  }

  
  /*
  
  public traducao(ArrayList<Dados> d) {
  this.d = d;
  }
  
  private boolean isAllConected() {
  Operadores OpAux;
  boolean resp = true;
  
  for (int i = 0; i < d.size(); i++) {
  if (d.get(i) != null && resp) {
  int size = d.get(i).getOp().size();
  for (int j = 0; j < size; j++) {
  OpAux = d.get(i).getOp().get(j);
  if (OpAux.getEnter1() != null) {
  if (!OpAux.getEnter1().isConected()) {
  resp = false;
  break;
  }
  }
  if (OpAux.getEnter2() != null) {
  if (!OpAux.getEnter2().isConected()) {
  resp = false;
  break;
  }
  }
  if (OpAux.getControl() != null) {
  if (!OpAux.getControl().isConected()) {
  resp = false;
  break;
  }
  }
  if (OpAux.getExit1() != null) {
  if (!OpAux.getExit1().isConected()) {
  resp = false;
  break;
  }
  }
  if (OpAux.getExit2() != null) {
  if (!OpAux.getExit2().isConected()) {
  resp = false;
  break;
  }
  }
  }
  if (!resp) {
  int opt = JOptionPane.showConfirmDialog(null,
  "Existem barramentos desconectados\n"
  + "Deseja continuar?",
  "!!! WARNING !!!", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null);
  if (opt == JOptionPane.OK_OPTION) {
  resp = true;
  Block2Code.logAdd("!!! Warning: Compilação iniciada com barramentos desconectados"
  + "\n\t o projeto final pode não está correto");
  } else {
  Block2Code.logAdd("Compilação cancelada pelo usuário"
  + "\n\t Existem barramentos desconectados");
  JOptionPane.showMessageDialog(null, "Tradução cancelada", null, JOptionPane.INFORMATION_MESSAGE);
  }
  }
  }
  }
  return resp;
  }
  
  
  private void addEntity(FileOutputStream fOut) throws compileException {
  Operadores OpAux;
  String texto;
  
  try {
  texto = "ENTITY " + ProjectName + " IS\r\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  texto = "PORT(";
  fOut.write(texto.getBytes(), 0, texto.length());
  
  //TO DO
  
  //      for (int i = 0; i < d.size(); i++) {
  //        if (d.get(i) != null) {
  //          int size = d.get(i).getOp().size();
  //          for (int j = 0; j < size; j++) {
  //            OpAux = d.get(i).getOp().get(j);
  //            if ((OpAux instanceof In) || (OpAux instanceof Out)) {
  //            }
  //          }
  //        }
  //      }
  
  texto = ");\r\nEND ENTITY;\r\n\r\n\r\n";
  fOut.write(texto.getBytes());
  } catch (IOException ex) {
  throw new compileException(ex.toString());
  }
  }
  
  private int indiceSubString(String mainString, String subString){
  int j = 0;
  int ponteiro = 0;
  for(int i = 0; i < mainString.length() ; i++){
  if(Character.toUpperCase(mainString.charAt(i)) == Character.toUpperCase(subString.charAt(j))){
  if(j == 0) ponteiro = i;
  j++;
  if(j == subString.length()) return ponteiro;
  }else{
  j = 0;
  }
  }
  return -1;
  }
  
  private void addPort(InputStream in, FileOutputStream fOut) throws Exception {
  int len;
  byte[] buf = new byte[3072];
  String texto;
  int indiceBegin = 0, indiceEnd;
  
  while ((len = in.read(buf)) > 0) {
  indiceBegin = indiceSubString(new String(buf),"port");
  indiceEnd = indiceSubString(new String(buf),"end");
  if ( indiceBegin != -1 && indiceEnd != -1) {
  fOut.write(buf, indiceBegin, indiceEnd - indiceBegin - 1);
  return;
  }
  }
  }
  
  private void addArchitecture(FileOutputStream fOut) throws Exception {
  Operadores OpAux;
  InputStream in;
  String texto;
  boolean branchFlag = false,
  copyFlag = false,
  dmergeFlag = false,
  deciderFlag = false,
  operatorFlag = false,
  vdmergeFlag = false,
  inFlag = false,
  outFlag = false;
  
  texto = "ARCHITECTURE Behavioral OF " + ProjectName + " IS\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  
  for (int i = 0; i < d.size(); i++) {
  if (d.get(i) != null) {
  int size = d.get(i).getOp().size();
  for (int j = 0; j < size; j++) {
  OpAux = d.get(i).getOp().get(j);
  
  if (OpAux instanceof Branch && !branchFlag) {
  texto = "\tCOMPONENT Branch ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/BRANCH.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  branchFlag = true;
  } else if (OpAux instanceof Copy && !copyFlag) {
  texto = "\tCOMPONENT Copy ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/COPY.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  copyFlag = true;
  } else if (OpAux instanceof DMerge && !dmergeFlag) {
  texto = "\tCOMPONENT dmerge ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/VDMERGE.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  dmergeFlag = true;
  } else if (OpAux instanceof Decider && !deciderFlag) {
  texto = "\tCOMPONENT decider ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/DECIDERG.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  deciderFlag = true;
  } else if (OpAux instanceof NDMerge && !vdmergeFlag) {
  texto = "\tCOMPONENT ndmerge ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/NDMERGE.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  vdmergeFlag = true;
  } else if (OpAux instanceof Operator && !operatorFlag) {
  texto = "\tCOMPONENT operator ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/OPERATOR.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  operatorFlag = true;
  } else if (OpAux instanceof In && !inFlag) {
  texto = "\tCOMPONENT inData ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/indata.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  inFlag = true;
  } else if (OpAux instanceof Out && !outFlag) {
  texto = "\tCOMPONENT outData ";
  fOut.write(texto.getBytes(), 0, texto.length());
  in = new FileInputStream(new File("src/Codigos/AOUT.vhd"));
  addPort(in, fOut);
  texto = "\tEND COMPONENT\n\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  outFlag = true;
  }
  }
  }
  }
  }
  
  
  
  private void addDados(FileOutputStream fOut) throws compileException {
  Operadores OpAux;
  String texto;
  
  try {
  texto = "BEGIN\r\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  for (int i = 0; i < d.size(); i++) {
  if (d.get(i) != null) {
  int size = d.get(i).getOp().size();
  for (int j = 0; j < size; j++) {
  OpAux = d.get(i).getOp().get(j);
  texto = "\t" + OpAux.getOpName() + ": " + OpAux.getOpTipe() + " PORT MAP " + "( ";
  if (OpAux.getEnter1() != null) {
  texto = texto + OpAux.getEnter1().getName();
  }
  if (OpAux.getEnter2() != null) {
  texto = texto + " , " + OpAux.getEnter2().getName();
  }
  if (OpAux.getControl() != null) {
  texto = texto + " , " + OpAux.getControl().getName();
  }
  if (OpAux.getExit1() != null) {
  texto = texto + " , " + OpAux.getExit1().getName();
  }
  if (OpAux.getExit2() != null) {
  texto = texto + " , " + OpAux.getExit2().getName();
  }
  texto = texto + " );\r\n";
  fOut.write(texto.getBytes());
  }
  }
  }
  
  texto = "END\r\n";
  fOut.write(texto.getBytes(), 0, texto.length());
  } catch (IOException ex) {
  throw new compileException(ex.toString());
  }
  }*/
}
